/*
 * Copyright 2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ltd.nullpointer.tcp.server.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import ltd.nullpointer.tcp.core.MessageDecoder;
import ltd.nullpointer.tcp.core.MessageEncoder;
import ltd.nullpointer.tcp.core.SessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description:
 * @CreateDate:2018年3月1日 下午2:16:26
 * @Author:zhangweilin
 */
@Component
public class NpChannelInitializer extends ChannelInitializer<SocketChannel> {
    // private final SslContext context;
    // private final boolean startTls;
    // private final boolean client;

    private static final EventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(50);
    @Autowired
    SessionManager sessionManager;
    @Autowired(required = false)
    @Qualifier("beforeByteToMessageDecoderList")
    List<ByteToMessageDecoder> beforeByteToMessageDecoderList;
    @Autowired(required = false)
    private AbstractServerChannelHandler serverChannelHandler;

    // public HlChannelInitializer(SslContext context, boolean client, boolean
    // startTls) {
    // this.context = context;
    // this.client = client;
    // this.startTls = startTls;
    // }

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {

        ChannelPipeline pipeline = socketChannel.pipeline();
        // SSLEngine engine = sslContext.newEngine(socketChannel.alloc()); // 2
        // engine.setUseClientMode(false); // 3 设置 SslEngine 是 client 或者是 server 模式
        // pipeline.addFirst("ssl", new SslHandler(engine)); // 4

        // Add the text line codec combination first,
//        pipeline.addLast(new DelimiterBasedFrameDecoder(1024 * 1024, Delimiters.lineDelimiter()));
//        if (CollectionUtils.isNotEmpty(beforeByteToMessageDecoderList)) {
////            pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,  3, 2,2,0));
//            for (ByteToMessageDecoder byteToMessageDecoder : beforeByteToMessageDecoderList) {
//                pipeline.addLast(byteToMessageDecoder);
//            }
//        }
        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 3, 2, 2, 0));
        pipeline.addLast(new IdleStateHandler(300, 300, 600));

        // 以下两行为拆包粘包解决
        // 参考 http://blog.csdn.net/u010853261/article/details/55803933
//        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 2, 0,
//                2));
//         pipeline.addLast(new LengthFieldPrepender(2, false));

        // the encoder and decoder are static as these are sharable
//        pipeline.addLast(new ServerDeciphMessageDecoder(sessionManager));
//        pipeline.addLast(new ServerEncryptMessageEncoder(sessionManager));
        pipeline.addLast(new MessageDecoder());
        pipeline.addLast(new MessageEncoder());

        pipeline.addLast(eventExecutorGroup, serverChannelHandler);
    }
}
